package com.lsh.ofc.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.base.common.exception.BusinessException;
import com.lsh.ofc.core.constant.Constants;
import com.lsh.ofc.core.entity.*;
import com.lsh.ofc.core.enums.*;
import com.lsh.ofc.core.exception.EC;
import com.lsh.ofc.core.model.DmgSoObd;
import com.lsh.ofc.core.model.DmgSoSo;
import com.lsh.ofc.core.service.OfcSoService;
import com.lsh.ofc.core.service.OrderSoObdService;
import com.lsh.ofc.core.util.DateUtil;
import com.lsh.ofc.core.util.IdGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * Project Name: lsh-ofc
 *
 * @author peter
 * @date 19/3/28
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Service
@Slf4j
public class OrderSoObdServiceImpl implements OrderSoObdService {

    @Autowired
    private OfcSoService ofcSoService;

    /**
     *
     * @param targetOfcSoHead
     * @param fromOrderHead
     * @return
     */
    @Override
    public OfcOrderHead ofcOrderHeadBuilder(OfcSoHead targetOfcSoHead, final OfcOrderHead fromOrderHead) {
        Integer time = (int) (System.currentTimeMillis() / 1000);
//       订单信息
        OfcOrderHead targetOrderHead = new OfcOrderHead();
        //完善订单信息
        targetOrderHead.setOrderCode(IdGenerator.genId());

        targetOrderHead.setFulfillStatus(FulfillStatus.CREATED.getValue());
        targetOrderHead.setTotalSkuReturnQty(BigDecimal.ZERO);
        targetOrderHead.setWarehouseCode(targetOfcSoHead.getWarehouseCode());
        targetOrderHead.setWarehouseName(targetOfcSoHead.getWarehouseName());
        targetOrderHead.setDistributionWay(DistributionWay.ORDER_2_USER.getValue());
        targetOrderHead.setOrderDistributionType(DistributionType.ORDER_SO.getCode());
        targetOrderHead.setPreWarehouseCode("0");
        targetOrderHead.setSecondDistributionFlag(0);
        targetOrderHead.setValid(Valid.enable.getValue());
        targetOrderHead.setOrderTime(time);
        targetOrderHead.setCreateTime(time);
        targetOrderHead.setUpdateTime(time);

        targetOrderHead.setRegionCode(fromOrderHead.getRegionCode());
        targetOrderHead.setAddressInfo(fromOrderHead.getAddressInfo());
        targetOrderHead.setAddressCode(targetOfcSoHead.getAddressCode());
        targetOrderHead.setExt(targetOfcSoHead.getExt());
        targetOrderHead.setOrderAmount(BigDecimal.ZERO);

        targetOrderHead.setVenderId(targetOfcSoHead.getVenderId());

        List<OfcSoDetail> soDetailList = targetOfcSoHead.getDetails();

        List<OfcOrderDetail> orderDetails = new ArrayList<>();
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal tatalOrderQty = BigDecimal.ZERO;
        BigDecimal tatalSupplyQty = BigDecimal.ZERO;
        OfcOrderDetail orderDetail;
        for (OfcSoDetail ofcSoDetail : soDetailList) {
            orderDetail = new OfcOrderDetail();

            orderDetail.setExt(ofcSoDetail.getExt());
            orderDetail.setGoodsCode(ofcSoDetail.getGoodsCode());
            orderDetail.setGoodsName(ofcSoDetail.getGoodsName());
            orderDetail.setGoodsAmount(ofcSoDetail.getGoodsAmount());
            totalAmount = totalAmount.add(ofcSoDetail.getGoodsAmount());
            orderDetail.setGoodsPrice(ofcSoDetail.getGoodsPrice());
            orderDetail.setGoodsSaleUnit(ofcSoDetail.getGoodsSaleUnit());
            orderDetail.setGoodsQty(ofcSoDetail.getSkuOrderQty().divide(ofcSoDetail.getGoodsSaleUnit(), 4, BigDecimal.ROUND_HALF_DOWN));
            orderDetail.setOrderCode(targetOrderHead.getOrderCode());
            orderDetail.setSkuCode(ofcSoDetail.getSkuCode());
            orderDetail.setCreateTime(ofcSoDetail.getCreateTime());
            orderDetail.setUpdateTime(ofcSoDetail.getUpdateTime());
            if(ofcSoDetail.getItemCode()!= null ){
                orderDetail.setItemCode(ofcSoDetail.getItemCode());
            }else{
                orderDetail.setItemCode(0);
            }

            orderDetail.setVenderId(ofcSoDetail.getVenderId());

            tatalOrderQty = tatalOrderQty.add(ofcSoDetail.getSkuOrderQty());
            tatalSupplyQty = tatalSupplyQty.add(ofcSoDetail.getSkuSupplyQty());
            orderDetails.add(orderDetail);
        }
        targetOrderHead.setDetails(orderDetails);
        targetOrderHead.setTotalSkuOrderQty(tatalOrderQty);
        targetOrderHead.setTotalSkuSupplyQty(tatalSupplyQty);
        targetOrderHead.setTotalSkuDeliverQty(BigDecimal.ZERO);

        return targetOrderHead;
    }

    /**
     *
     * @param soSoMap
     * @param redisSoDetailMap
     * @return
     */
    @Override
    public OfcSoHead ofcSoHeadBuilder(Map<String, List<DmgSoSo>> soSoMap, Map<Integer, JSONObject> redisSoDetailMap) {

        OfcSoHead ofcSoHead = new OfcSoHead();
        ofcSoHead.setSoBillCode(IdGenerator.getId());

        Integer time = (int) (System.currentTimeMillis() / 1000);
        BigDecimal totalOrderQty = BigDecimal.ZERO;
        BigDecimal totalSupplyQty = BigDecimal.ZERO;
        String sumSoId = "";
        OfcSoHead soHead = null;
        Map<Integer, OfcSoDetail> sumSoDetailMap = new HashMap<>();
        String soCode = "";
        for (Map.Entry<String, List<DmgSoSo>> soEntry : soSoMap.entrySet()) {

            String soId = soEntry.getKey();
            List<DmgSoSo> soList = soEntry.getValue();

            if (soHead == null) {
                OfcSoHead fitler = new OfcSoHead();
                fitler.setSoBillCode(soId);
                soHead = ofcSoService.findOne(fitler, false);
            }

            Map<String, OfcSoDetail> soDetailMap = this.getSoDetails(soId);

            for (DmgSoSo soSo : soList) {
                String key = soSo.getSoId() + ":" + soSo.getSoOrderItem();
                OfcSoDetail ofcSoDetail = soDetailMap.get(key);
                Integer sumSoItemNo = soSo.getSumSoOrderItem();
                sumSoId = soSo.getSumSoId();
                if (null == ofcSoDetail) {
                    log.warn(key + " 对应的so 详情信息不存在");
                    throw new BusinessException(EC.ERROR.getCode(), key + " 对应的so 详情信息不存在");
                }
                soCode = soSo.getSapId();
                log.info(key + " : sumSoItemNo :" + sumSoItemNo);
                OfcSoDetail sumSoDetail = sumSoDetailMap.get(sumSoItemNo);
                if (null == sumSoDetail) {
                    sumSoDetail = new OfcSoDetail();
                    BeanUtils.copyProperties(ofcSoDetail, sumSoDetail);

                    Integer sumSoOrderItem = soSo.getSumSoOrderItem();

                    sumSoDetail.setId(null);
                    sumSoDetail.setSkuOrderQty(BigDecimal.ZERO);
                    sumSoDetail.setSkuSupplyQty(BigDecimal.ZERO);
                    sumSoDetail.setSkuReturnQty(BigDecimal.ZERO);
                    sumSoDetail.setGoodsAmount(BigDecimal.ZERO);
                    sumSoDetail.setItemNo(sumSoOrderItem);
                    sumSoDetail.setItemCode(sumSoOrderItem);
                    sumSoDetail.setSoBillCode(ofcSoHead.getSoBillCode());

                    String ext = sumSoDetail.getExt();
                    JSONObject soExt;
                    if (StringUtils.isEmpty(ext)) {
                        soExt = new JSONObject();
                    } else {
                        soExt = JSON.parseObject(ext);
                    }

                    JSONObject redisSoDetail = redisSoDetailMap.get(sumSoOrderItem);
                    soExt.put("price", redisSoDetail.getString("price"));
                    sumSoDetail.setExt(soExt.toJSONString());

                    sumSoDetailMap.put(sumSoItemNo, sumSoDetail);
                }

                sumSoDetail.setSkuOrderQty(sumSoDetail.getSkuOrderQty().add(soSo.getQuantity()));
                if (sumSoId.startsWith("lk")) {
                    sumSoDetail.setSkuSupplyQty(sumSoDetail.getSkuSupplyQty().add(soSo.getOccupy()));
                } else {
                    sumSoDetail.setSkuSupplyQty(sumSoDetail.getSkuSupplyQty().add(soSo.getQuantity()));
                }

                totalOrderQty = totalOrderQty.add(soSo.getQuantity());
                totalSupplyQty = totalSupplyQty.add(soSo.getOccupy());
            }
        }
        // 取订单信息 特殊处理
        ofcSoHead.setOrderCode(soHead.getOrderCode());

        ofcSoHead.setRegionCode(soHead.getRegionCode());
        ofcSoHead.setSupplierId(soHead.getSupplierId());
        ofcSoHead.setSupplierOrg(soHead.getSupplierOrg());
        ofcSoHead.setSupplierDc(soHead.getSupplierDc());

        ofcSoHead.setSupplierCode(soHead.getSupplierCode());
        ofcSoHead.setSupplierGroup(soHead.getSupplierGroup());

        ofcSoHead.setWarehouseCode(soHead.getWarehouseCode());
        ofcSoHead.setWarehouseName(soHead.getWarehouseName());
        ofcSoHead.setFulfillWms(soHead.getFulfillWms());
        ofcSoHead.setFulfillChannel(soHead.getFulfillChannel());
        ofcSoHead.setSoStatus(SoStatus.CREATED.getValue());
        ofcSoHead.setDistributionWay(DistributionWay.ORDER_2_USER.getValue());
        ofcSoHead.setSecondDistributionFlag(0);
        ofcSoHead.setOrderDistributionType(DistributionType.ORDER_SO.getCode());
        ofcSoHead.setPreWarehouseCode("0");
        ofcSoHead.setValid(Valid.enable.getValue());
        ofcSoHead.setTotalSkuOrderQty(totalOrderQty);
        ofcSoHead.setTotalSkuDeliverQty(BigDecimal.ZERO);
        ofcSoHead.setTotalSkuReturnQty(BigDecimal.ZERO);
        ofcSoHead.setCreateTime(time);
        ofcSoHead.setOrderTime(time);
        ofcSoHead.setUpdateTime(time);
        ofcSoHead.setSoCode(soCode);
        ofcSoHead.setDetails(new ArrayList<>(sumSoDetailMap.values()));
        ofcSoHead.setAddressCode(soHead.getAddressCode());
        ofcSoHead.setVenderId(soHead.getVenderId());

        JSONObject soExt = JSON.parseObject(soHead.getExt());
        soExt.put(Constants.ORDER_H_SUM_SOID, sumSoId);
        if (sumSoId.startsWith("lk")) {
            ofcSoHead.setTotalSkuSupplyQty(totalSupplyQty);
        } else {
            ofcSoHead.setTotalSkuSupplyQty(totalOrderQty);
        }
        soExt.put(Constants.ORDER_H_SUM_FLAG, SumFlag.SUM.getCode());
        soExt.put(Constants.WUMARTFILL, WumartFill.IS_NOT_WUMARKT_FILL_2_PSI.getValue());

        ofcSoHead.setExt(soExt.toJSONString());

        return ofcSoHead;
    }

    /**
     *
     * @param ofcSoHead
     * @param soObdList
     * @return
     */
    @Override
    public OfcObdHead ofcObdHeadBuilder(OfcSoHead ofcSoHead, List<DmgSoObd> soObdList) {

        Integer time = (int) (System.currentTimeMillis() / 1000);
        List<OfcSoDetail> soDetailList = ofcSoHead.getDetails();
//       obd 信息创建
        Map<Integer, OfcSoDetail> soDetailMap = new HashMap<>();
        for (OfcSoDetail soDetail : soDetailList) {
            soDetailMap.put(soDetail.getItemNo(), soDetail);
        }

        List<OfcObdDetail> ofcObdDetailList = new ArrayList<>();
        String obdCode = "";
        BigDecimal totalDeliverQty = BigDecimal.ZERO;
        BigDecimal costAmount = BigDecimal.ZERO;
        BigDecimal costNtAmount = BigDecimal.ZERO;
        String soCode = "";
        for (DmgSoObd soObd : soObdList) {

            OfcSoDetail soDetail = soDetailMap.get(soObd.getSoOrderItem());

            OfcObdDetail obdDetail = new OfcObdDetail();
            JSONObject soExt = JSON.parseObject(soDetail.getExt());
            soExt.put(Constants.OBD_D_PACK_NUM, "");
            soExt.put(Constants.OBD_D_BOX_NUM, "");
            soExt.put(Constants.OBD_D_LEFT_EA_NUM, "");

            obdDetail.setSoBillCode(soDetail.getSoBillCode());
            obdDetail.setSkuCode(soDetail.getSkuCode());
            obdDetail.setSkuSupplyCode(soDetail.getSkuSupplyCode());
            obdDetail.setExt(soExt.toJSONString());
            obdDetail.setCreateTime(time);
            obdDetail.setUpdateTime(time);
            obdDetail.setTaxRate(soDetail.getTaxRate());
            obdDetail.setSkuSupplyPrice(soDetail.getSkuSupplyPrice());
            obdDetail.setSkuDeliverQty(soObd.getObdOccupy());
            obdDetail.setSkuReturnQty(BigDecimal.ZERO);

            obdDetail.setVenderId(ofcSoHead.getVenderId());
            //
            totalDeliverQty = totalDeliverQty.add(soObd.getObdOccupy());
            //
            ofcObdDetailList.add(obdDetail);
            //
            obdCode = soObd.getObdId();
            soCode = soObd.getSapId();
        }
        if (StringUtils.isEmpty(obdCode)) {
            obdCode = "0";
        }

        OfcObdHead ofcObdHead = new OfcObdHead();

        ofcObdHead.setSoBillCode(ofcSoHead.getSoBillCode());
        ofcObdHead.setOrderCode(ofcSoHead.getOrderCode());
        ofcObdHead.setFulfillWms(ofcSoHead.getFulfillWms());
        ofcObdHead.setFulfillChannel(ofcSoHead.getFulfillChannel());
        ofcObdHead.setWarehouseCode(ofcSoHead.getWarehouseCode());
        ofcObdHead.setWarehouseName(ofcSoHead.getWarehouseName());
        ofcObdHead.setTotalSkuOrderQty(ofcSoHead.getTotalSkuOrderQty());
        ofcObdHead.setTotalSkuSupplyQty(ofcSoHead.getTotalSkuSupplyQty());
        ofcObdHead.setTotalSkuReturnQty(ofcSoHead.getTotalSkuReturnQty());
        ofcObdHead.setTotalSkuDeliverQty(totalDeliverQty);
        ofcObdHead.setRegionCode(ofcSoHead.getRegionCode());
        ofcObdHead.setSupplierDc(ofcSoHead.getSupplierDc());
        ofcObdHead.setSupplierId(ofcSoHead.getSupplierId());
        ofcObdHead.setSupplierOrg(ofcSoHead.getSupplierOrg());
        ofcObdHead.setCostAmount(costAmount.setScale(2, BigDecimal.ROUND_HALF_UP));
        ofcObdHead.setCostNtAmount(costNtAmount.setScale(2, BigDecimal.ROUND_HALF_UP));
        ofcObdHead.setCreateTime(time);
        ofcObdHead.setUpdateTime(time);

        ofcObdHead.setVenderId(ofcSoHead.getVenderId());

        JSONObject json = new JSONObject();
        json.put(Constants.OBD_H_CREATE_TIME, ObjectUtils.toString(null));
        json.put(Constants.OBD_H_DELIVERY_TIME, DateUtil.defaultDate(new Date()));

        ofcObdHead.setExt(json.toJSONString());
        ofcObdHead.setValid(Valid.enable.getValue());
        ofcObdHead.setSoCode(soCode);
        ofcObdHead.setObdCode(obdCode);

        ofcObdHead.setDetails(ofcObdDetailList);

        return ofcObdHead;
    }

    /**
     *
     * @param soId
     * @return
     */
    private Map<String, OfcSoDetail> getSoDetails(String soId) {

        OfcSoHead fiter = new OfcSoHead();
        fiter.setSoBillCode(soId);
        List<OfcSoDetail> soDetails = ofcSoService.findDtails(soId);
        Map<String, OfcSoDetail> soDetailMap = new HashMap<>();
        for (OfcSoDetail ofcSoDetail : soDetails) {
            Integer itemNo = ofcSoDetail.getItemNo();

            String soBillCode = ofcSoDetail.getSoBillCode();

            soDetailMap.put(soBillCode + ":" + itemNo, ofcSoDetail);
        }

        return soDetailMap;
    }

}
